#include "assert.h"
#include <cstdlib>
#include "stdio.h"
#include "stdlib.h"

#include "../../include/SDL.h"
#include "../../structs.h"

using namespace std;

unsigned int contarNodos(Lista*);
extern "C" Lista* constructor_lista();
extern "C" void inicializar_nodo(Nodo* nuevo, SDL_Surface *surfacePers, SDL_Surface *surfaceGen, Uint32 x, Uint32 y, Uint32 ID);
extern "C" bool verificar_id (Lista* la_lista, Uint32 id);
extern "C" void agregar_item_ordenado(Lista* la_lista, SDL_Surface* surfacePers, SDL_Surface* surfaceGen, Uint32 x, Uint32 y, Uint32 ID);
extern "C" void borrar(Lista* la_lista, Uint32 x, Uint32 y);
extern "C" void liberar_lista(Lista* l);
extern "C" Iterador* constructor_iterador(Lista *lista);
extern "C" void proximo(Iterador *iter);
extern "C" Nodo* item(Iterador *iter);
extern "C" bool hay_proximo(Iterador *iter);
extern "C" void liberar_iterador(Iterador *iter);

unsigned int contarNodos(Lista* lista)
{
	unsigned int nodos = 0;
	Nodo *nodo = lista->primero;
	
	while(nodo != NULL) {
		nodos++;
		nodo = nodo->prox;
	}
	
	return nodos;
}

int main()
{
	SDL_Surface* surfacePers = (SDL_Surface*) malloc(sizeof(struct SDL_Surface));
	SDL_Surface* surfaceGen = (SDL_Surface*) malloc(sizeof(struct SDL_Surface));
				
	Lista* lista;
	
	Uint32 caso = 1;
	Uint32 casos = 100 * 3;
	
	printf("Testeando agregar_item_ordenado:\n");
	
	//para distintas longitudes de lista
	for(Uint32 i = 1; i <= 100; i++)
	{
		printf("caso %d de %d\n", caso++, casos);
		
		//lista que le agrego nodos con ids al azar
		lista = constructor_lista();
		
		if(lista != NULL)
		{
			for(Uint32 j = 0; j < i; j++)
			{
				int randomN = random();

				agregar_item_ordenado(lista,surfacePers,surfaceGen,i,i,randomN);
				assert(!verificar_id(lista,randomN));
				assert(contarNodos(lista) == j+1);
			}
			
			liberar_lista(lista);
		}
		
		printf("caso %d de %d\n", caso++, casos);
		
		//lista que le agrego nodos con ids siempre al inicio
		lista = constructor_lista();
		
		if(lista != NULL)
		{
			for(Uint32 j = 0; j < i; j++)
			{
				agregar_item_ordenado(lista,surfacePers,surfaceGen,i,i,i - j);
				assert(!verificar_id(lista,i - j));
				assert(contarNodos(lista) == j+1);
			}
			
			liberar_lista(lista);
		}
		
		printf("caso %d de %d\n", caso++, casos);
		
		//lista que le agrego nodos con ids siempre al final
		lista = constructor_lista();
		
		if(lista != NULL)
		{
			for(Uint32 j = 0; j < i; j++)
			{
				agregar_item_ordenado(lista,surfacePers,surfaceGen,i,i,j);
				assert(!verificar_id(lista,j));
				assert(contarNodos(lista) == j+1);
			}
			
			liberar_lista(lista);
		}
	}
	
	caso = 1;
	casos = 50 * 50;
	
	printf("Testeando borrar:\n");
	
	//punto x desde el cual borro
	for(Uint32 x_borrar = 51; x_borrar <= 100; x_borrar++)
	{
		//punto y desde el cual borro
		for(Uint32 y_borrar = 51; y_borrar <= 100; y_borrar++)
		{
			printf("caso %d de %d\n", caso++, casos);
		
			//creo una lista de 100 x 100
			//0 <= x, y <= 100
			lista = constructor_lista();
		
			if(lista != NULL)
			{
				Uint32 i = 100 * 100;
		
				for(Uint32 x = 0; x < 100; x++)
				{
					for(Uint32 y = 0; y < 100; y++)
					{
						agregar_item_ordenado(lista,surfacePers,surfaceGen,x,y,i--);
					}
				}
		
				//me fijo si la lista es de 100 x 100
				assert(i == 0);
		
				//borro desde el punto que queria
				borrar(lista, x_borrar, y_borrar);
		
				//me fijo si quedo la cantidad de nodos que deberia quedar
				i = 100 * 100;
				assert(contarNodos(lista) == i - (50 + (100 - x_borrar)) * (50 + (100 - y_borrar)));
		
				liberar_lista(lista);
			}
		}
	}
	
	if(surfacePers != NULL) free((void*)surfacePers);
	if(surfaceGen != NULL) free((void*)surfaceGen);
	
	return 0;
}
